home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
public
/
bit
/
src
/
merge.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
17KB
|
689 lines
/*
* $Id: merge.c,v 0.91 1994/02/20 00:53:25 zhao Pre-Release $
*
*. This file is part of BIT shareware package. After the two weeks of
* free evaluation period, you are encouraged (required) to register
* your copy for a small registration fee, which is $35 for personal use
* and $50 for commercial, government and institutional use.
*
* Copyright(c) 1993, 1994 by T.C. Zhao.
* All rights reserved.
*
* Permission to use, copy, and distribute this software in its entirety
* for non-commercial purposes is hereby granted, provided that the
* above shareware and copyright notices and this permission notice
* appear in all copies and their documentation.
*
* This software may be modified for your own use, but modified versions
* may not be distributed without prior consent of the author.
*
* This software is provided "as is" without expressed or implied
* warranty of any kind.
*
*.
*
* Purpose:
* Merge/concatinate/overlay two or more images to form a
* single image.
*
*/
#if !defined(lint) && defined(F_ID)
char *id_mg = "$Id: merge.c,v 0.91 1994/02/20 00:53:25 zhao Pre-Release $";
#endif
#include "bit.h"
#include "extern.h"
/******************* Limits and defines **************************/
#define MAXOFF 300.0 /* max overlapping */
#define ImageOK (ir->w > 0) /* if new image load */
/***************** Local variables ******************************/
static Rect_t imrect, *imr; /* current image size (global) */
static Rect_t iirect, *ir; /* loaded image size */
static IPTR mi; /* the load image itself */
static IPTR oim; /* input image */
static int showmi = 0; /* if show image while moving */
static int autosize; /* if update image size */
static int alignreq = 4; /* requested allignment */
static int sep; /* sepetation */
static int mergebot; /* which on top if overlap */
static int fillc[4]; /* fill color */
static FL_FORM *imerge;
static int offx, offy; /* where original image is */
/******* Possible operations on the image ******************/
typedef struct
{
const char *name; /* operation name */
int matop; /* known by the matrix rouines */
}
Matop;
static Matop matops[] =
{
{"Overwrite", O_NONE,},
{" Add ", O_ADD},
{" Sub ", O_SUB},
{" Diff ", O_DIFF},
{" XOR ", O_XOR},
{" Mask ", O_MASK}
};
static Matop *mop = matops;
/******* Local functions **************************************/
static void create_form_imerge(void);
static int merge_init(IPTR, int);
static void
show_image(int ox, int oy, int x, int y)
{
if (!mi || !showmi)
return;
mv_ras_obj(mi->mraster, mi->w, mi->h, ox, oy, x, y);
}
/******************************************************************
* Global entry point
*****************************************************************/
int
do_merge(IPTR im)
{
short val;
long dev;
create_form_imerge();
deactivate_all_forms();
oim = im;
mi = 0;
/*
* initialize and install handler to handle window manager's resize and
* reposition events
*/
merge_init(im, 0);
install_wm_handler(merge_init);
/* disable bounds checking */
set_rubber_bounds(0, 0, 0, 0, 0);
bit_show_form(imerge, FL_PLACE_MOUSE, 0, "Imerge");
/* looping until ESC or done button is pressed */
do
{
if (alignreq == 0 && ImageOK)
{
dev = rubber_info(win_id, &val,
&ir->x, &ir->y, &ir->w, &ir->h, 2, 0);
dev = bit_handle_event(dev, val);
}
else
dev = bit_qread(&val);
}
while (!(dev == KEYBD && val == 27));
/* clean up */
remove_wm_handler(merge_init);
rubber_finish();
bit_hide_form(imerge);
free_image(mi);
fl_activate_all_forms();
return 0;
}
/*************************************************************
* find where the rubber should be (ix, iy). The current image
* location is given by (xi, xf, w, h)
*
* Location request is defined as follows:
*
* 7 8 9
* 17 19
* 4 image 6
* 11 13
* 1 2 3
*
*************************************************************/
/* ARGSUSED */
static void
get_location(IPTR im)
{
int xf = imr->x + imr->w - 1;
int yf = imr->y + imr->h - 1;
int xi = imr->x, yi = imr->y;
int w = imr->w, h = imr->h;
int iw = ir->w, ih = imr->h;
switch (alignreq)
{
case 1:
ir->x = xi;
ir->y = yi - ih - sep;
break;
case 2:
ir->x = xi + (w - iw) / 2;
ir->y = yi - ih - sep;
break;
case 3:
ir->x = xf - iw + 1;
ir->y = yi - ih - sep;
break;
case 7:
ir->x = xi;
ir->y = yf + 1 + sep;
break;
case 8:
ir->x = xi + (w - iw) / 2;
ir->y = yf + 1 + sep;
break;
case 9:
ir->x = xf - iw + 1;
ir->y = yf + 1 + sep;
break;
case 6:
ir->x = xf + 1 + sep;
ir->y = yi + (h - ih) / 2;
break;
case 11:
ir->x = xi - iw - sep;
ir->y = yi;
break;
case 17:
ir->x = xi - iw - sep;
ir->y = yf - ih + 1;
break;
case 4:
ir->x = xi - iw - sep;
ir->y = yi + (h - ih) / 2;
break;
case 19:
ir->x = xf + 1 + sep;
ir->y = yf - ih + 1;
break;
case 13:
ir->x = xf + 1 + sep;
ir->y = yi;
break;
}
}
static void
place_rubber(IPTR im)
{
int ox = ir->x, oy = ir->y;
if (ir->w == 0 || ir->h == 0)
return;
get_location(im);
set_current_window(win_id);
rubber_moveto(&ir->x, &ir->y, &ir->w, &ir->h);
show_image(ox, oy, ir->x, ir->y);
rubber_show(alignreq ? 1 : 2); /* change rubber_color */
}
/******************************************************************
* Initialize the rubber band location. If wme == 1, it is called
* by the window manager envents handler or purposely not updating
* current alignment reference
******************************************************************/
static int
merge_init(IPTR im, int wme)
{
if (!wme)
{
offx = offy = 0;
imr = &imrect;
copy_rect(imr, img_rect(im));
ir = &iirect;
ir->w = ir->h = 0;
}
else
{
/* image & window size might've been changed */
imr->x = im->xi + offx;
imr->y = im->yi + offy;
}
place_rubber(im);
return 0;
}
/********** Load the image to merge *******************************/
/*ARGSUSED*/
static void
load_cb(FL_OBJECT * ob, long q)
{
const char *fn = getfilename("Files to merge", ".", "*", "", 0);
IPTR tmpi;
if (!fn || !(tmpi = load_image(fn)))
return;
free_image(mi);
/* show current image info, which was reset in load_image */
update_image_info(imgptr);
mi = tmpi;
set_current_window(win_id);
rubber_hide();
ir->w = tmpi->w;
ir->h = tmpi->h;
get_location(imgptr);
rubber_new(win_id, ir->x, ir->y, ir->w, ir->h, alignreq ? 1 : 2);
}
/*ARGSUSED*/
static void
top_bottom_cb(FL_OBJECT * ob, long q)
{
mergebot = fl_get_choice(ob) - 1;
}
/*ARGSUSED*/
static void
update_size_cb(FL_OBJECT * ob, long q)
{
merge_init(imgptr, 0);
}
/******************************************************************
* Do the actual merging, taking into account the top/bottom
* settings
******************************************************************/
/*ARGSUSED*/
static void
merge_it(FL_OBJECT * ob, long q)
{
rgba_t **mat, fcolor;
const Rect_t *sum, *uu;
if (!ImageOK)
return;
/* figure out the new image size */
sum = sum_rect(img_rect(oim), ir);
/* merged image will always be in RGB */
if (img_convert_type(oim, T_RGBA) || img_convert_type(mi, T_RGBA))
return;
show_busy("PleaseWait ...");
/* get the new image matrix and initialize to the request bk color */
mat = get_mat(sum->h, sum->w, sizeof(rgba_t));
fcolor = Pack(fillc[0], fillc[1], fillc[2]);
init_mat(mat, sum->h, sum->w, sizeof(rgba_t), fcolor);
mi->xi = ir->x;
mi->yi = ir->y;
mi->xf = ir->x + ir->w - 1;
mi->yf = ir->y + ir->h - 1;
/*
* always remember where the original image is by remembering the
* distance from lower-left corner of the original image to the
* lower-left corner of the merged image
*/
offx = imr->x - sum->x;
offy = imr->y - sum->y;
/*
* further optimization is possible in that for concatenation, the image
* itself IS the submat and we can simple use the image matrix and thus
* avoiding the submat operation
*/
if (mergebot) /* new image at bottom */
{
put_submat(mat, sum->h, sum->w, mi->mraster,
ir->y - sum->y, ir->x - sum->x,
ir->h, ir->w, sizeof(rgba_t));
put_submat(mat, sum->h, sum->w, oim->mraster,
oim->yi - sum->y, oim->xi - sum->x,
oim->h, oim->w, sizeof(rgba_t));
}
else
{
/* insert subimages */
put_submat(mat, sum->h, sum->w, oim->mraster,
oim->yi - sum->y, oim->xi - sum->x,
oim->h, oim->w, sizeof(rgba_t));
put_submat(mat, sum->h, sum->w, mi->mraster,
ir->y - sum->y, ir->x - sum->x,
ir->h, ir->w, sizeof(rgba_t));
}
/*
* do requested operation on the overlapping part of the images only,
* taking into consideration the top/bottom requests
*/
if (mop->matop != O_NONE && (uu = union_rect(img_rect(oim), ir)))
{
rgba_t **m1, **m2;
Rect_t urect;
Rect_t *u = &urect;
copy_rect(u, uu);
/*
* m1 is the input matrix, m2 is the image old image and mat is
* the resulting image
*/
m1 = get_subimage(mi, u->x, u->y, u->w, u->h);
m2 = get_subimage(oim, u->x, u->y, u->w, u->h);
set_mat_op(mop->matop);
M_info("Merge", "Op=%s\n", mop->name);
put_submat(mergebot ? m1 : m2, u->h, u->w, mergebot ? m2 : m1,
0, 0, u->h - 1, u->w - 1, sizeof(**m2));
set_mat_op(O_NONE);
put_submat(mat, sum->h, sum->w, mergebot ? m1 : m2,
u->y - sum->y, u->x - sum->x,
u->h, u->w, sizeof(rgba_t));
free_mat(m1);
free_mat(m2);
}
fill_image_struct(oim, mat, sum->h, sum->w, T_RGBA);
set_current_window(win_id);
set_display_mode(oim);
/* don't move the image unless requested */
if (!autosize)
{
oim->xi = sum->x;
oim->yi = sum->y;
oim->xf = oim->xi + sum->w - 1;
oim->yf = oim->yi + sum->h - 1;
Rectwrite(sum->x, sum->y,
sum->x + sum->w - 1, sum->y + sum->h - 1, oim->raster);
}
else
{
oim->io->display(oim, 0, double_buf);
}
merge_init(oim, !autosize); /* re-initialize */
end_busy();
}
/***************** Alignment information **************
*
* 7 8 9
* 17 19
* 4 6
* 11 13
* 1 2 3
*******************************************************/
#if 0
extern void set_rubber_info_cb(void (*)(int, int, int, int));
#endif
/* ARGSUSED */
static void
alignment_cb(FL_OBJECT * ob, long q)
{
if (alignreq == 0) /* manual */
{
set_rubber_info_cb(0);
end_rubber_info();
}
alignreq = q;
place_rubber(imgptr);
#if 0
if (alignreq == 0)
{
set_rubber_info_cb(show_image);
}
#endif
}
/************ Terminating Merge function *************/
/* ARGSUSED*/
static void
merge_done(FL_OBJECT * ob, long q)
{
fl_qenter(KEYBD, 27);
}
/************* Seperation from the image ***************/
/*ARGSUSED*/
static void
sep_cb(FL_OBJECT * ob, long q)
{
sep = fl_get_counter_value(ob);
place_rubber(imgptr);
}
#define FILLCI 300
/***************** Fill color ***********************/
/* ARGSUSED*/
static void
fc_cb(FL_OBJECT * ob, long q)
{
get_color(imgptr, fillc, 1);/* block */
fl_mapcolor(FILLCI, fillc[0], fillc[1], fillc[2]);
fl_redraw_object(ob);
}
/******** Get the requested operation struct *****/
static void
operation_cb(FL_OBJECT * ob, long q)
{
if ((q = fl_get_choice(ob)) > 0)
mop = matops + q - 1;
}
static FL_OBJECT *ialign;
static void
create_form_imerge(void)
{
FL_OBJECT *obj;
float dx, dy, x, y;
Matop *m = matops, *ms = m + sizeof(matops) / sizeof(matops[0]);
if (imerge)
return;
imerge = fl_bgn_form(FL_NO_BOX, 275.0, 250.0);
obj = fl_add_box(FL_UP_BOX, 0.0, 0.0, 275.0, 250.0, "");
obj = fl_add_text(FL_NT, 35.0, 210.0, 200.0, 30.0, "Image Merge");
fl_set_object_lcol(obj, 4);
fl_set_object_lsize(obj, 16.0);
fl_set_object_align(obj, FL_ALIGN_CENTER);
fl_set_object_lstyle(obj, FL_BOLD_STYLE);
obj = fl_add_button(FL_HB, 0, 0.0, 275.0, 250.0, "");
fl_set_call_back(obj, help_cb, HELP_MERGE);
dx = 75.0;
dy = 25.0;
x = 185.0;
y = 175.0;
/* Operations */
obj = fl_add_choice(FL_NC, x, y, dx, dy, "");
fl_set_object_boxtype(obj, FL_ROUNDED_BOX);
fl_set_choice_fontsize(obj, 10.0);
while (m < ms)
{
fl_addto_choice(obj, m->name);
m++;
}
fl_set_choice(obj, 1);
fl_set_call_back(obj, operation_cb, 0);
y -= dy + 1;
/* top/bottom */
obj = fl_add_choice(FL_NC, x, y, dx, dy, "");
fl_set_object_boxtype(obj, FL_ROUNDED_BOX);
fl_set_choice_fontsize(obj, 10.0);
fl_addto_choice(obj, "Top");
fl_addto_choice(obj, "Bottom");
fl_set_choice(obj, mergebot + 1);
fl_set_call_back(obj, top_bottom_cb, 0);
y -= dy + 5;
dx = 75.0;
dy = 25.0;
x = 185.0;
obj = fl_add_button(FL_NB, x, y, dx, dy, "FillColor");
fl_set_object_lsize(obj, 10.0);
fl_set_object_color(obj, FILLCI, FL_GREEN);
fl_set_object_lcol(obj, FL_MAGENTA);
fl_set_object_lstyle(obj, FL_BOLD_STYLE);
fl_set_call_back(obj, fc_cb, 0);
y -= dy;
obj = fl_add_button(FL_NB, x, y, dx, dy, "UpdateSize");
fl_set_object_lsize(obj, 10.0);
fl_set_call_back(obj, update_size_cb, 0);
y -= dy;
obj = fl_add_button(FL_NB, x, y, dx, dy, "Image2M");
fl_set_object_lsize(obj, 10.0);
fl_set_call_back(obj, load_cb, 0);
y -= dy + 5;
obj = fl_add_button(FL_NB, x, y, dx, dy, "Merge");
fl_set_object_lsize(obj, 10.0);
fl_set_call_back(obj, merge_it, 0);
y -= dy;
obj = fl_add_button(FL_NB, x, y, dx, dy, "Done");
fl_set_object_lsize(obj, 10.0);
fl_set_call_back(obj, merge_done, 0);
/* Seperation control */
obj = fl_add_counter(FL_NC, 30.0, 15.0, 130.0, 25.0, "");
fl_set_counter_precision(obj, 0);
fl_set_counter_bounds(obj, -MAXOFF, MAXOFF);
fl_set_counter_step(obj, 1.0, 10.0);
fl_set_counter_value(obj, sep);
fl_set_call_back(obj, sep_cb, 0);
/* all the alignment buttons */
/* 7 8 9
17 19
4 6
11 13
1 2 3
*/
ialign = fl_bgn_group();
dx = dy = 30.0;
y = 10;
obj = fl_add_button(FL_RB, 55.0, y + 70.0, 90.0, 90.0, "Manual");
fl_set_object_color(obj, 47, 12);
fl_set_call_back(obj, alignment_cb, 0);
/* center buttons */
/* right-center */
obj = fl_add_button(FL_RB, 145.0, y + 100.0, dx, dy, "@circle");
fl_set_object_lcol(obj, 1);
fl_set_call_back(obj, alignment_cb, 6);
fl_set_button(obj, alignreq == 6);
/* bottom */
obj = fl_add_button(FL_RB, 85.0, y + 40.0, dx, dy, "@circle");
fl_set_object_lcol(obj, 1);
fl_set_call_back(obj, alignment_cb, 2);
fl_set_button(obj, alignreq == 2);
/* left */
obj = fl_add_button(FL_RB, 25.0, y + 100.0, dx, dy, "@circle");
fl_set_object_lcol(obj, 1);
fl_set_call_back(obj, alignment_cb, 4);
fl_set_button(obj, alignreq == 4);
/* top */
obj = fl_add_button(FL_RB, 85.0, y + 160.0, dx, dy, "@circle");
fl_set_object_lcol(obj, 1);
fl_set_call_back(obj, alignment_cb, 8);
fl_set_button(obj, alignreq == 8);
/* bottom two */
obj = fl_add_button(FL_RB, 55.0, y + 40.0, dx, dy, "@4");
fl_set_object_lcol(obj, 1);
fl_set_call_back(obj, alignment_cb, 1);
fl_set_button(obj, alignreq == 1);
obj = fl_add_button(FL_RB, 115.0, y + 40.0, dx, dy, "@6");
fl_set_object_lcol(obj, 1);
fl_set_call_back(obj, alignment_cb, 3);
fl_set_button(obj, alignreq == 3);
/* top two */
obj = fl_add_button(FL_RB, 55.0, y + 160.0, dx, dy, "@4");
fl_set_object_lcol(obj, 1);
fl_set_call_back(obj, alignment_cb, 7);
fl_set_button(obj, alignreq == 7);
obj = fl_add_button(FL_RB, 115.0, y + 160.0, dx, dy, "@6");
fl_set_object_lcol(obj, 1);
fl_set_call_back(obj, alignment_cb, 9);
fl_set_button(obj, alignreq == 9);
/* left two */
obj = fl_add_button(FL_RB, 25.0, y + 70.0, dx, dy, "@2");
fl_set_object_lcol(obj, 1);
fl_set_call_back(obj, alignment_cb, 11);
fl_set_button(obj, alignreq == 11);
obj = fl_add_button(FL_RB, 25.0, y + 130.0, dx, dy, "@8");
fl_set_object_lcol(obj, 1);
fl_set_call_back(obj, alignment_cb, 17);
fl_set_button(obj, alignreq == 17);
/* right two */
obj = fl_add_button(FL_RB, 145.0, y + 130.0, dx, dy, "@8");
fl_set_object_lcol(obj, 1);
fl_set_call_back(obj, alignment_cb, 19);
fl_set_button(obj, alignreq == 19);
obj = fl_add_button(FL_RB, 145.0, y + 70.0, dx, dy, "@2");
fl_set_object_lcol(obj, 1);
fl_set_call_back(obj, alignment_cb, 13);
fl_set_button(obj, alignreq == 13);
fl_end_group();
fl_end_form();
}